﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using EPiServer.Common.Categories;
using EPiServer.Community.Blog;
using JoelAbrahamsson.TestUtilities;
using Moq;
using StructureMap.AutoMocking;
using Xunit;

namespace JoelAbrahamsson.MetaWeblog.Tests
{
    public class UpdateEntryCategoriesTests
    {
        [Fact]
        public void GivenCategoryTitles_UpdateEntryCategories_AddsCategories()
        {
            Mock<Entry> fakeEntry = new Mock<Entry>();
            fakeEntry.Setup(entry => entry.Categories).Returns(new CategoryCollection());
            string[] categoryInfoTitles = new [] { RandomValues.String, RandomValues.String };
            Mock<ICategory> fakeExpectedCategoryOne = new Mock<ICategory>();
            fakeExpectedCategoryOne.Object.Name = RandomValues.String;
            fakeExpectedCategoryOne.Setup(category => category.ID).Returns(1);
            Mock<ICategory> fakeExpectedCategoryTwo = new Mock<ICategory>();
            fakeExpectedCategoryTwo.Object.Name = RandomValues.String;
            fakeExpectedCategoryTwo.Setup(category => category.ID).Returns(2);
            ICategory[] expectedCategories = 
                new []
                    {
                        fakeExpectedCategoryOne.Object,
                        fakeExpectedCategoryTwo.Object
                    };
            MoqAutoMocker<MetaWeblogHandler> metaWeblogHandlerAutoMocker = new MoqAutoMocker<MetaWeblogHandler>();
            Mock<IBlogCategoryProvider> fakeBlogCategoryProvider = Mock.Get(metaWeblogHandlerAutoMocker.Get<IBlogCategoryProvider>());
            fakeBlogCategoryProvider.Setup(provider => provider.ParseCategory(categoryInfoTitles[0])).Returns(expectedCategories[0]);
            fakeBlogCategoryProvider.Setup(provider => provider.ParseCategory(categoryInfoTitles[1])).Returns(expectedCategories[1]);
            MetaWeblogHandler metaWeblogHandler = metaWeblogHandlerAutoMocker.ClassUnderTest;

            metaWeblogHandler.UpdateEntryCategories(fakeEntry.Object, categoryInfoTitles);

            foreach (ICategory expectedCategory in expectedCategories)
            {
                Assert.Contains(expectedCategory, fakeEntry.Object.Categories, new CategoryNameComparer());
            }
        }

        private class CategoryNameComparer : IComparer<ICategory>
        {
            public int Compare(ICategory x, ICategory y)
            {
                if (x.Name == y.Name)
                    return 0;

                return -1;
            }
        }

        [Fact]
        public void GivenCategoryTitles_UpdateEntryCategories_DoesNotAddAlreadyAddedCategories()
        {
            Mock<Entry> fakeEntry = new Mock<Entry>();
            fakeEntry.Setup(entry => entry.Categories).Returns(new CategoryCollection());
            string[] categoryInfoTitles = new[] { RandomValues.String };
            ICategory categoryToAdd = new EPiServer.Common.Categories.Category(RandomValues.String);
            fakeEntry.Object.Categories.Add(categoryToAdd);
            MoqAutoMocker<MetaWeblogHandler> metaWeblogHandlerAutoMocker = new MoqAutoMocker<MetaWeblogHandler>();
            Mock<IBlogCategoryProvider> fakeBlogCategoryProvider = Mock.Get(metaWeblogHandlerAutoMocker.Get<IBlogCategoryProvider>());
            fakeBlogCategoryProvider.Setup(provider => provider.ParseCategory(categoryInfoTitles[0])).Returns(categoryToAdd);
            MetaWeblogHandler metaWeblogHandler = metaWeblogHandlerAutoMocker.ClassUnderTest;

            metaWeblogHandler.UpdateEntryCategories(fakeEntry.Object, categoryInfoTitles);

            Assert.Equal(1, fakeEntry.Object.Categories.Count);
        }

        [Fact]
        public void GivenCategoryTitles_UpdateEntryCategories_RemovesExistingCategoriesThatAreNotRepresentedInTitles()
        {
            Mock<Entry> fakeEntry = new Mock<Entry>();
            fakeEntry.Setup(entry => entry.Categories).Returns(new CategoryCollection() { new EPiServer.Common.Categories.Category(RandomValues.String) });
            string[] categoryInfoTitles = new string[0];
            MoqAutoMocker<MetaWeblogHandler> metaWeblogHandlerAutoMocker = new MoqAutoMocker<MetaWeblogHandler>();
            MetaWeblogHandler metaWeblogHandler = metaWeblogHandlerAutoMocker.ClassUnderTest;

            metaWeblogHandler.UpdateEntryCategories(fakeEntry.Object, categoryInfoTitles);

            Assert.Equal(0, fakeEntry.Object.Categories.Count);
        }
    }
}
